package me.buick.util.jmeter.snmpprocessvisualizers;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

import me.buick.util.jmeter.snmpprocess.snmpmgmt.SNMPProcessSampleResult;
import me.buick.util.snmp.core.pojo.ProcessInfoPojo;

import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.visualizers.MonitorModel;
import org.apache.jorphan.gui.RendererUtils;
import org.apache.jorphan.reflect.Functor;

public class SNMPProcessDetailPane  extends SNMPProcessBorderedComponent{
	
	private static final long serialVersionUID = 6477891859661249355L;

	private SortableObjectTableModel model = null;

    private JTable table = null;
    
    private final Map<String, ProcessInfoPojo> tableRows = Collections.synchronizedMap(new HashMap<String, ProcessInfoPojo>());

    private JScrollPane tableScrollPanel = null;
	
    private static final String[] COLUMNS = new String[] {
        "PID",  // $NON-NLS-1$
        "PROCName",  // $NON-NLS-1$
        "PROCParams", // $NON-NLS-1$
        "CPUUsage(%)",                // $NON-NLS-1$
        "MEMUsage(KBytes)", // $NON-NLS-1$
        "PROCType",      // $NON-NLS-1$
        "PROCStat" };     // $NON-NLS-1$

    // 	Column renderers
    private static final TableCellRenderer[] RENDERERS =
    new TableCellRenderer[]{
        null, // PID
        null, // ProcName
        null, // ProcParam
        null, // CPUUsage
        null, // MEMUsage
        null, // ProcType
        null, // ProcStat
    };
	
	public SNMPProcessDetailPane() {
    	super("Detail View");
		setLayout(new BorderLayout(0, 0));
        model = new SortableObjectTableModel(COLUMNS,
        		ProcessInfoPojo.class,         // The object used for each row
                new Functor[] {
                new Functor("getPid"), // $NON-NLS-1$
                new Functor("getProcName"),
                new Functor("getProcParameters"), // $NON-NLS-1$
                new Functor("getCPUPerc"), // $NON-NLS-1$
                new Functor("getProcPerfMemKBytes"), // $NON-NLS-1$
                new Functor("getProcTypeString"), // $NON-NLS-1$
                new Functor("getProcRunningStatusString") }, // $NON-NLS-1$
                new Functor[] { null, null, null, null, null, null, null },
                new Class[] {
                Integer.class, String.class, String.class, Double.class, Integer.class, String.class, String.class });
        init();
    }
	
	private void init() {
		
        this.setLayout(new BorderLayout());

        // Set up the table itself
        table = new JTable(model);
        table.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer());
        model.addMouseListener(table);
        // table.getTableHeader().setReorderingAllowed(false);
        RendererUtils.applyRenderers(table, RENDERERS);

        tableScrollPanel = new JScrollPane(table);
        tableScrollPanel.setViewportBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));

        // Set up the table with footer
        JPanel tablePanel = new JPanel();

        tablePanel.setLayout(new BorderLayout());
        tablePanel.add(tableScrollPanel, BorderLayout.CENTER);

        // Add the main panel and the graph
        this.add(tablePanel, BorderLayout.CENTER);
    }
	
	public void updateProcessDetailInfo(MonitorModel result) {
		SNMPProcessMonitorModel snmpResult = (SNMPProcessMonitorModel) result;
		this.add(snmpResult.getOriginalSampleResult());
	}

    public String getLabelResource() {
        return "view_results_in_table"; // $NON-NLS-1$
    }

    public synchronized void add(SampleResult res) {
    	if(res != null){
    		SNMPProcessSampleResult snmpres = (SNMPProcessSampleResult)res;
    		Map<Integer, ProcessInfoPojo> ppjm = snmpres.getProcessPojoMap();
    		for(Integer pid : ppjm.keySet()){
    			ProcessInfoPojo tempPojo = tableRows.get(pid.toString());
    			if(tempPojo != null){
    				ProcessInfoPojo valueObj = ppjm.get(pid);
    				tempPojo.setCPUPerc((valueObj.getCPUPerc())*100);
    				tempPojo.setProcRunningStatus(valueObj.getProcRunningStatus());
    				tempPojo.setProcPerfMemKBytes(valueObj.getProcPerfMemKBytes());
    			}else{
    				ProcessInfoPojo valueObj = ppjm.get(pid);
    				valueObj.setCPUPerc((valueObj.getCPUPerc())*100);
    				tableRows.put(pid.toString(), valueObj);
    				model.addRow(valueObj);
    			}
    		}
    		if(ppjm.size() != tableRows.size()){
    			List<Integer> removeList = new ArrayList<Integer>();
    			for(String pidstr : tableRows.keySet()){
    				Integer pid = Integer.parseInt(pidstr);
    				ProcessInfoPojo tp = ppjm.get(pid);
    				if(tp == null){
    					removeList.add(pid);
    				}
    			}
    			List<ProcessInfoPojo> tempList = model.getRows();
    			Map<Integer, ProcessInfoPojo> tempMap = model.getRowPIDMap();
    			for(Integer pid : removeList){
    				tempList.remove(tempMap.get(pid));
    			}
    		}
    		if(model.hasOrdered()){
    			model.sort(true);
    		}
    		model.fireTableDataChanged();
    	}    	
  }

    public synchronized void clearData() {
        model.clearData();
        tableRows.clear();
        repaint();
    }

    public String toString() {
        return "Show the samples in a table";
    }
	
}
